﻿using Link_eLab.Redis.Base;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Link_eLab.SqlSugar.Base
{
    public class BaseDao<T> : BaseRedis<T>, IBaseDao<T> where T : class, new()
    {
        public async Task<bool> Any(Expression<Func<T, bool>> whereExpression)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Queryable<T>().AnyAsync(whereExpression);
        }

        public async Task<int> Delete(string id)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Deleteable<T>().In(id).ExecuteCommandAsync();
        }

        public async Task<int> Delete(Expression<Func<T, bool>> whereExpression)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Deleteable<T>().Where(whereExpression).ExecuteCommandAsync();
        }

        public async Task<int> Insert(T entity)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Insertable<T>(entity).ExecuteReturnIdentityAsync();
        }

        public async Task<List<T>> QueryAll()
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Queryable<T>().ToListAsync();
        }

        public async Task<List<TResult>> QueryBySql<TResult>(string sql, object whereObj = null)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            var res = dbClient.Ado.SqlQuery<TResult>(sql, whereObj);
            return await Task.Run(() => res);
        }

        public async Task<int> ExecuteBySql(string sql, object whereObj = null)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            int res = dbClient.Ado.ExecuteCommand(sql, whereObj);
            return await Task.Run(() => res);
        }

        public async Task<List<TResult>> QueryBySqlTransactions<TResult>(string sql, object whereObj = null)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            try
            {
                dbClient.Ado.BeginTran();
                var res = dbClient.Ado.SqlQuery<TResult>(sql, whereObj);
                return await Task.Run(() => res);
            }
            catch (Exception ex)
            {
                dbClient.Ado.RollbackTran();
                throw new Exception(ex.Message);
            }
        }

        public async Task<List<T>> QueryByWhere(Expression<Func<T, object>> whereExpression,
            Expression<Func<T, object>> orderExpression, OrderByType orderType = OrderByType.Asc)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Queryable<T>().In(whereExpression).OrderByIF(orderExpression != null, orderExpression, orderType).ToListAsync();
        }

        public async Task<List<T>> QueryByWhere(Expression<Func<T, bool>> whereExpression,
            Expression<Func<T, object>> orderExpression, OrderByType orderType = OrderByType.Asc)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Queryable<T>().WhereIF(whereExpression != null, whereExpression).OrderByIF(orderExpression != null, orderExpression, orderType).ToListAsync();
        }

        public async Task<List<T>> QueryByWherePage(int pageIndex, int pageSize, Expression<Func<T, object>> whereExpression,
            Expression<Func<T, object>> orderExpression, OrderByType orderType = OrderByType.Asc)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Queryable<T>().In(whereExpression).OrderByIF(orderExpression != null, orderExpression, orderType).ToPageListAsync(pageIndex, pageSize);
        }

        public async Task<List<T>> QueryByWherePage(int pageIndex, int pageSize, Expression<Func<T, bool>> whereExpression,
            Expression<Func<T, object>> orderExpression, OrderByType orderType = OrderByType.Asc)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Queryable<T>().WhereIF(whereExpression != null, whereExpression).OrderByIF(orderExpression != null, orderExpression, orderType).ToPageListAsync(pageIndex, pageSize);
        }

        public async Task<int> QueryCount(Expression<Func<T, object>> whereExpression = null)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Queryable<T>().In(whereExpression).CountAsync();
        }

        public async Task<int> QueryCount(Expression<Func<T, bool>> whereExpression = null)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Queryable<T>().WhereIF(whereExpression != null, whereExpression).CountAsync();
        }

        public async Task<int> QueryCount(List<IConditionalModel> searchParam)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Queryable<T>().Where(searchParam).CountAsync();
        }

        public async Task<T> QuerySingle(string id)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            var res = dbClient.Queryable<T>().InSingle(id);
            return await Task.Run(() => res);
        }

        public async Task<T> QuerySingle(Expression<Func<T, bool>> whereExpression)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            var res = await dbClient.Queryable<T>().FirstAsync(whereExpression);
            return res;
        }

        public async Task<int> Update(T entity)
        {
            using SqlSugarClient dbClient = DbInstance.GetInstance();
            return await dbClient.Updateable(entity).ExecuteCommandAsync();
        }

        public async Task<int> Update(List<T> entity)
        {
            using (SqlSugarClient dbClient = DbInstance.GetInstance())
            {
                try
                {
                    dbClient.Ado.BeginTran();
                    return await dbClient.Updateable(entity).ExecuteCommandAsync();
                }
                catch (Exception ex)
                {
                    dbClient.Ado.RollbackTran();
                    throw new Exception(ex.Message);
                }
            }
        }

        public async Task<int> Update(Expression<Func<T, T>> updateColumns, Expression<Func<T, bool>> whereExpression)
        {
            using (SqlSugarClient dbClient = DbInstance.GetInstance())
            {
                return await dbClient.Updateable(updateColumns).Where(whereExpression).ExecuteCommandAsync();
            }
        }
    }
}